﻿using System.Collections.Concurrent;
using System.Net;
using System.Net.Sockets;
using System.Text;


namespace TcpServerTest
{
    public sealed class Net
    {
        // 完全懒汉实例化
        //private Net() { }
        //public static Net Instance => Nested.instance;
        //private class Nested
        //{
        //    static Nested() { }
        //    internal static readonly Net instance = new();
        //}
        // 完全懒汉实例化


        // Lazy
        private static readonly Lazy<Net> lazyInstance = new(() => new Net());
        private Net() { }
        public static Net Instance => lazyInstance.Value;
        // Lazy


        /// <summary>
        /// 示例端口号
        /// </summary>
        private const int port = 65532;

        private const int headLength = 4;


        public void AddListener()
        {
            // 创建TcpListener并绑定到指定的IP地址和端口
            TcpListener listener = new(IPAddress.Any, port);
            listener.Start();

            IPAddress localIPv4 = ((IPEndPoint)listener.LocalEndpoint).Address.MapToIPv4();
            IPAddress localIPv6 = ((IPEndPoint)listener.LocalEndpoint).Address.MapToIPv6();
            //int portListener = ((IPEndPoint)listener.LocalEndpoint).Port;
            Console.WriteLine($"IPv4 address: {localIPv4}");
            Console.WriteLine($"IPv6 address: {localIPv6}");
            //Console.WriteLine($"服务器已启动，监听端口 {portListener}...");
            Console.WriteLine($"服务器已启动，监听端口 {port}...");

            try
            {
                while (true)
                {
                    // 等待客户端连接
                    TcpClient client = listener.AcceptTcpClient();
                    Console.WriteLine($"客户端已连接：{client.Client.RemoteEndPoint}");

                    // 处理客户端请求
                    _ = Task.Run(() => HandleClient(client));
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"发生错误：{ex.Message}");
            }
            finally
            {
                listener.Stop();
            }

        }

        private async void HandleClient(TcpClient client)
        {
            try
            {
                // 获取客户端的网络流
                NetworkStream stream = client.GetStream();

                ConcurrentQueue<byte[]> _needHandleBytes = new();

                while (true)
                {
                    byte[] headBytes = new byte[headLength];

                    int bytesReceived = await stream.ReadAsync(headBytes, 0, headLength);

                    int dataLenght = BitConverter.ToInt32(headBytes);

                    if (dataLenght == 0)
                    {
                        continue;
                    }

                    byte[] dataBytes = new byte[dataLenght];
                    int bytesReceived1 = await stream.ReadAsync(dataBytes, 0, dataLenght);

                    if (bytesReceived1 > 0)
                    {
                        _needHandleBytes.Enqueue(dataBytes);
                    }

                    //这段应该写到异步函数中去
                    while (!_needHandleBytes.IsEmpty)
                    {
                        _ = _needHandleBytes.TryDequeue(out byte[]? dataBytes1);

                        string receivedMessage = Encoding.UTF8.GetString(dataBytes1, 0, dataBytes1.Length);
                        Console.WriteLine($"收到客户端消息：{receivedMessage}");


                        string responseMessage = "服务端收到了你的消息：" + receivedMessage;

                        //for (int i = 0; i < 100; i++)
                        //{
                        await SendStr(stream, responseMessage);
                        //}
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"处理客户端请求时发生错误：{ex.Message}");
            }
            finally
            {
                Console.WriteLine($"跟客户端断开连接：{client.GetHashCode()}");
                client.Dispose();
            }
        }

        private async Task SendStr(NetworkStream stream, string responseMessage)
        {
            Console.WriteLine($"给客户端发消息：{responseMessage}");
            byte[] dataBytes = Encoding.UTF8.GetBytes($"{responseMessage}\n");
            await SendBytes(stream, dataBytes);
        }

        private async Task SendBytes(NetworkStream stream, byte[] dataBytes)
        {
            int dataLenght = dataBytes.Length;
            byte[] headBytes = BitConverter.GetBytes(dataLenght);
            int packageLength = headLength + dataLenght;
            byte[] packageBytes = new byte[packageLength];
            Buffer.BlockCopy(headBytes, 0, packageBytes, 0, headLength);
            Buffer.BlockCopy(dataBytes, 0, packageBytes, headLength, dataLenght);
            await stream.WriteAsync(packageBytes, 0, packageBytes.Length);
        }

    }
}